/*
 * $Id: ParamServiceImpl.java 1096 2011-07-04 03:36:31Z jyang $
 * 
 * Copyright (c) 2001-2008 Accentrix Company Limited. All Rights Reserved.
 * 
 * Accentrix Company Limited. ("Accentrix") retains copyright on all text, source
 * and binary code contained in this software and documentation. Accentrix grants
 * Licensee a limited license to use this software, provided that this copyright
 * notice and license appear on all copies of the software. The software source
 * code is provided for reference purposes only and may not be copied, modified 
 * or distributed.
 * 
 * THIS SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS," WITHOUT ANY WARRANTY OF
 * ANY KIND UNLESS A SEPARATE WARRANTIES IS PURCHASED FROM ACCENTRIX AND REMAINS
 * VALID.  ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
 * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 * PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. ACCENTRIX SHALL NOT BE LIABLE
 * FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING OR MODIFYING THE
 * SOFTWARE OR ITS DERIVATIVES.
 * 
 * IN NO EVENT WILL ACCENTRIX BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR
 * FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES,
 * HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE
 * USE OF OR INABILITY TO USE SOFTWARE, EVEN IF ACCENTRIX HAS BEEN ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 */
package com.lightsaber.trade.cloth.service.param.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.lightsaber.trade.cloth.dao.param.AwardDao;
import com.lightsaber.trade.cloth.dao.param.CampusDao;
import com.lightsaber.trade.cloth.dao.param.DeptDao;
import com.lightsaber.trade.cloth.dao.param.DisciplineAcadSemDao;
import com.lightsaber.trade.cloth.dao.param.GarTypeDao;
import com.lightsaber.trade.cloth.dao.param.ParmDao;
import com.lightsaber.trade.cloth.dao.param.ProgBoardDao;
import com.lightsaber.trade.cloth.dao.programme.ProgrammeDao;
import com.lightsaber.trade.cloth.entity.archive.ArchivedImage;
import com.lightsaber.trade.cloth.entity.category.Category;
import com.lightsaber.trade.cloth.entity.param.Award;
import com.lightsaber.trade.cloth.entity.param.Campus;
import com.lightsaber.trade.cloth.entity.param.Dept;
import com.lightsaber.trade.cloth.entity.param.DisciplineAcadSem;
import com.lightsaber.trade.cloth.entity.param.GarType;
import com.lightsaber.trade.cloth.entity.param.Parm;
import com.lightsaber.trade.cloth.entity.param.ProgBoard;
import com.lightsaber.trade.cloth.entity.programme.ProgrammeStatus;
import com.lightsaber.trade.cloth.service.param.ParamObject;
import com.lightsaber.trade.cloth.service.param.ParamService;

@Service
@Transactional
public class ParamServiceImpl implements ParamService {

    private final static Logger log = LoggerFactory.getLogger(ParamServiceImpl.class);

    private static final String SEGMENT = "id.segment";

    @Autowired
    private ParmDao parmDao;

    @Autowired
    private ProgrammeDao programmeDao;

    @Autowired
    private DisciplineAcadSemDao disciplineAcadSemDao;

    @Autowired
    private GarTypeDao garTypeDao;

    @Autowired
    private AwardDao awardDao;

    @Autowired
    private CampusDao campusDao;

    @Autowired
    private DeptDao deptDao;
    @Autowired
    private ProgBoardDao progBoardDao;

    @Override
    public List<ParamObject> getCampusList() {
        List<Campus> list = campusDao.getAll();
        return getFromCampus(list);
    }

    @Override
    public List<ParamObject> getBureauList() {
        List<Parm> parms = parmDao.findBy(SEGMENT, BUREAU);
        return getFromParm(parms);
    }

    /**
     * <pre>
     * S Subvented 
     * M Market Fee 
     * Y Self Financed
     * </pre>
     */
    @Override
    public List<ParamObject> getFundingModeList() {
        List<Parm> parms = parmDao.findBy(SEGMENT, FUNDING_MODE);
        return getFromParm(parms);
    }

    @Override
    public String getFundingModeLabel(final String value) {
        Map<String, String> map = getFundingModeMap();
        return map.get(value);
    }

    public Map<String, String> getFundingModeMap() {

        List<ParamObject> paramList = getFundingModeList();

        Map<String, String> map = new HashMap<String, String>();
        for (ParamObject param : paramList) {
            map.put(param.getCode(), param.getDesc());
        }
        return map;
    }

    @Override
    public List<ParamObject> getProgrammeAttributesList() {
        List<Parm> parms = parmDao.findBy(SEGMENT, PROGRAMME_ATTRIBUTES);
        return getFromParm(parms);
    }

    /**
     * <pre>
     * FT   FT  Full-time
     * PTDR    PTDR    Part-time Day-release
     * PTEM    PTEM    Part-time Evening Module Accumulation
     * PTES    PTES    Part-time Stage-based
     * 
     * </pre>
     */
    @Override
    public List<ParamObject> getStudyModeList() {
        List<Parm> parms = parmDao.findBy(SEGMENT, STUDY_MODE);
        return getFromParm(parms);
    }

    @Override
    public String getStudyModeLabel(final String value) {
        Map<String, String> map = getStudyModeMap();
        return map.get(value);
    }

    public Map<String, String> getStudyModeMap() {

        List<ParamObject> paramList = getStudyModeList();

        Map<String, String> map = new HashMap<String, String>();
        for (ParamObject param : paramList) {
            map.put(param.getCode(), param.getDesc());
        }
        return map;
    }

    @Override
    public List<ParamObject> getProgrammeTypeList() {
        List<Parm> parms = parmDao.findBy(SEGMENT, PROGRAMME_TYPE);
        return getFromParm(parms);
    }

    @Override
    public List<ParamObject> getLevelOfStudyList() {
        List<Parm> parms = parmDao.findBy(SEGMENT, LEVEL_OF_STUDY);
        return getFromParm(parms);
    }

    @Override
    public List<ParamObject> getPreEmploymentInServiceList() {
        List<Parm> parms = parmDao.findBy(SEGMENT, PRE_EMP_IN_SER);
        return getFromParm(parms);
    }

    @Override
    public List<ParamObject> getProgammeStatusList() {
        List<Parm> parms = parmDao.findBy(SEGMENT, PROGAMME_STATUS);
        return getFromParm(parms);
    }

    @Override
    public List<ParamObject> getPaaList() {
        List<Parm> parms = parmDao.findBy(SEGMENT, PAA);
        return getFromParm(parms);
    }

    @Override
    public String getPaaLabel(final String paa) {
        Map<String, String> map = getPaaMap();
        return map.get(paa);
    }

    public Map<String, String> getPaaMap() {

        List<ParamObject> paramList = getPaaList();

        Map<String, String> map = new HashMap<String, String>();
        for (ParamObject param : paramList) {
            map.put(param.getCode(), param.getDesc());
        }
        return map;
    }

    @Override
    public List<ParamObject> getSubPaaList() {
        List<Parm> parms = parmDao.findBy(SEGMENT, SUB_PAA);
        return getFromParm(parms);
    }

    @Override
    public String getSubPaaLabel(final String paa) {
        Map<String, String> map = getSubPaaMap();
        return map.get(paa);
    }

    public Map<String, String> getSubPaaMap() {

        List<ParamObject> paramList = getSubPaaList();

        Map<String, String> map = new HashMap<String, String>();
        for (ParamObject param : paramList) {
            map.put(param.getCode(), param.getDesc());
        }
        return map;
    }

    @Override
    public List<ParamObject> getMainStreamList() {
        List<Parm> parms = parmDao.findBy(SEGMENT, MAIN_STREAM);
        return getFromParm(parms);
    }

    @Override
    public List<ParamObject> getSubjectGroupList() {
        List<Parm> parms = parmDao.findBy(SEGMENT, SUBJECT_GROUP);
        return getFromParm(parms);
    }

    @Override
    public List<ParamObject> getMinimumnEntryLevelList() {
        List<Parm> parms = parmDao.findBy(SEGMENT, MINIMUMN_ENTRY_LEVEL);
        return getFromParm(parms);
    }

    @Override
    public List<ParamObject> getUnitList() {
        List<Parm> parms = parmDao.findBy(SEGMENT, UNIT);
        return getFromParm(parms);
    }

    @Override
    public List<ParamObject> getProgrammeBoardList() {
        List<ProgBoard> progBoards = progBoardDao.getAll();
        return getProgBoards(progBoards);

    }

    private List<ParamObject> getProgBoards(List<ProgBoard> progBoards) {
        List<ParamObject> list = new ArrayList<ParamObject>();

        for (ProgBoard progBoard : progBoards) {
            list.add(new ParamObjectImpl(progBoard.getProgBoard(), progBoard.getProgBoardDesc()));
        }

        return list;
    }

    @Override
    public List<ParamObject> getDisciplineList() {
        List<DisciplineAcadSem> disciplines = disciplineAcadSemDao
                .getLatestAcademicYearDiciplineList();
        return getFromDiscipline(disciplines);
    }

    @Override
    public String getDisciplineLabel(final String value) {
        Map<String, String> map = getDisciplineMap();
        return map.get(value);
    }

    public Map<String, String> getDisciplineMap() {

        List<ParamObject> paramList = getDisciplineList();

        Map<String, String> map = new HashMap<String, String>();
        for (ParamObject param : paramList) {
            map.put(param.getCode(), param.getDesc());
        }
        return map;
    }

    @Override
    public List<ParamObject> getGarTypeList() {
        List<GarType> garTypes = garTypeDao.getAll();
        return getFromGarType(garTypes);
    }

    @Override
    public List<ParamObject> getRevisionTypeList() {
        List<Parm> parms = parmDao.findBy(SEGMENT, REVISION_TYPE);
        return getFromParm(parms);
    }

    @Override
    public String getRevisionTypeLabel(final String revisionType) {
        Map<String, String> map = getRevisionTypeMap();
        return map.get(revisionType);
    }

    public Map<String, String> getRevisionTypeMap() {
        List<ParamObject> paramList = this.getRevisionTypeList();
        Map<String, String> map = new HashMap<String, String>();
        for (ParamObject param : paramList) {
            map.put(param.getCode(), param.getDesc());
        }
        return map;
    }

    @Override
    public List<ParamObject> getAwardList() {
        List<Parm> parms = parmDao.findBy(SEGMENT, AWARD_TYPE);
        return getFromParm(parms);
    }

    @Override
    public List<ParamObject> getAllTypeList() {
        String[][] paramss = { { PROGRAMME_CODE, "Programme Code" }, { DISCIPLINE, "Discipline" },
                { AWARD, "Award" }, { PRE_EMP_IN_SER, "Pre-employment / In-Service" },
                { MAIN_STREAM, "Main Stream" }, { STUDY_MODE, "Study Mode" },
                { LEVEL_OF_STUDY, "Level of Study" },
                { MINIMUMN_ENTRY_LEVEL, "Minimumn Entry Level" }, { DURATION, "Duration" },
                { QF_LEVEL, "QF Level" }, { GAR_TYPE, "GAR Type" },
                { PROGRAMME_STATUS, "Programme Status" }, { PROGRAMME_TYPE, "Programme Type" } };
        return ParamObjectImpl.makeList(paramss);
    }

    @Override
    public String getTypeLabel(String type) {
        List<ParamObject> paramList = getAllTypeList();
        Map<String, String> map = new HashMap<String, String>();
        for (ParamObject param : paramList) {
            map.put(param.getCode(), param.getDesc());
        }
        return map.get(type);
    }

    @Override
    public String getLableByCodeAndValue(final String code, final String value) {
        List<ParamObject> paramList = getByCode(code);
        Map<String, String> map = new HashMap<String, String>();
        for (ParamObject param : paramList) {
            map.put(param.getCode(), param.getDesc());
        }
        return map.get(value);
    }

    @Override
    public List<ParamObject> getByCode(final String code) {
        List<ParamObject> poList = null;

        if (code.equals(PROGRAMME_CODE)) {
            poList = new ArrayList<ParamObject>();

            List<Object> codeList = programmeDao.getAllProgrammeCodes();
            for (Object oj : codeList) {
                poList.add(new ParamObjectImpl(oj.toString(), oj.toString()));
            }
        } else if (code.equals(IS_STREAM_OR_PROGRAMME)) {
            poList = getIsStreamOrProgrammelist();

        } else if (code.equals(DISCIPLINE)) {
            poList = getDisciplineList();

        } else if (code.equals(CLASSIFICATION)) {
            poList = getProgrammeClassificationList();

        } else if (code.equals(QF_LEVEL)) {
            poList = getQFLevelList();

        } else if (code.equals(MAIN_STREAM)) {
            poList = getMainStreamList();

        } else if (code.equals(AWARD)) {
            poList = getAwardList();

        } else if (code.equals(PRE_EMP_IN_SER)) {
            poList = getPreEmploymentInServiceList();

        } else if (code.equals(PROGRAMME_STATUS)) {
            poList = getProgrammeStatusList();

        } else if (code.equals(GAR_TYPE)) {
            poList = getGarTypeList();

        } else if (code.equals(STUDY_MODE)) {
            poList = getStudyModeList();

        } else if (code.equals(LEVEL_OF_STUDY)) {
            poList = getLevelOfStudyList();

        } else if (code.equals(PROGRAMME_TYPE)) {
            poList = getProgrammeTypeList();

        } else if (code.equals(DURATION)) {
            poList = getDurationList();

        } else if (code.equals(MINIMUMN_ENTRY_LEVEL)) {
            poList = getMinimumnEntryLevelList();
            
        } else if (code.equals(FUNDING_MODE)) {
            poList = getFundingModeList();
        }

        return poList;
    }

    public List<ParamObject> getProgrammeStatusList() {
        List<ParamObject> list = new ArrayList<ParamObject>();

        for (ProgrammeStatus sta : ProgrammeStatus.values()) {
            list.add(new ParamObjectImpl(sta.toString(), sta.toString()));
        }

        return list;
    }

    @Override
    public List<ParamObject> getQFLevelList() {
        String[][] paramss = { { "1", "level 1" }, { "2", "level 2" }, { "3", "level 3" },
                { "4", "level 4" } };
        return ParamObjectImpl.makeList(paramss);
    }

    @Override
    public String getQFLevelLabel(final String qFLevel) {
        Map<String, String> map = getQFLevelMap();
        return map.get(qFLevel);
    }

    public Map<String, String> getQFLevelMap() {
        List<ParamObject> paramList = this.getQFLevelList();
        Map<String, String> map = new HashMap<String, String>();
        for (ParamObject param : paramList) {
            map.put(param.getCode(), param.getDesc());
        }
        return map;
    }

    @Override
    public List<ParamObject> getIsStreamOrProgrammelist() {
        String[][] paramss = { { "Stream", "Stream" }, { "Programme", "Programme" } };
        return ParamObjectImpl.makeList(paramss);
    }

    @Override
    public List<ParamObject> getDurationList() {
        String[][] paramss = { { "1", "1 Year" }, { "2", "2 Year" }, { "3", "3 Year" },
                { "4", "4 Year" } };
        return ParamObjectImpl.makeList(paramss);
    }

    @Override
    public List<ParamObject> getAllTypeCodeMapDisplay() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public List<ParamObject> getExternalExaminerList() {
        String[][] paramss = { { "Examiner1", "Examiner 1" }, { "Examiner2", "Examiner 2" } };
        return ParamObjectImpl.makeList(paramss);
    }

    private List<ParamObject> getFromParm(final List<Parm> parms) {
        int size = parms.size();

        String[][] paramss = new String[size][2];
        for (int i = 0; i < size; i++) {
            paramss[i][0] = parms.get(i).getId().getCode();
            paramss[i][1] = parms.get(i).getAttrib01();
        }
        return ParamObjectImpl.makeList(paramss);
    }

    private List<ParamObject> getFromDiscipline(final List<DisciplineAcadSem> disciplines) {
        int size = disciplines.size();

        String[][] paramss = new String[size][2];
        for (int i = 0; i < size; i++) {
            paramss[i][0] = disciplines.get(i).getDisciplineDisplayCode();// here
                                                                          // modified
                                                                          // by
                                                                          // dj
            paramss[i][1] = disciplines.get(i).getShortDesc();// here modified

        }
        return ParamObjectImpl.makeList(paramss);
    }

    private List<ParamObject> getFromGarType(final List<GarType> garTypes) {
        int size = garTypes.size();

        String[][] paramss = new String[size][2];
        for (int i = 0; i < size; i++) {
            paramss[i][0] = garTypes.get(i).getGarType();
            paramss[i][1] = garTypes.get(i).getShortDesc();
        }
        return ParamObjectImpl.makeList(paramss);
    }

    private List<ParamObject> getFromAward(final List<Award> awards) {
        int size = awards.size();

        String[][] paramss = new String[size][2];
        for (int i = 0; i < size; i++) {
            paramss[i][0] = awards.get(i).getId().getAward();
            paramss[i][1] = awards.get(i).getTitle();
        }
        return ParamObjectImpl.makeList(paramss);
    }

    /* add by dj */
    private List<ParamObject> getFromCampus(final List<Campus> campuses) {
        int size = campuses.size();

        String[][] paramss = new String[size][2];
        for (int i = 0; i < size; i++) {
            paramss[i][0] = campuses.get(i).getCampus();// here modified by dj
            paramss[i][1] = campuses.get(i).getCampusDisplayCode();// here
                                                                   // modified
                                                                   // by dj
        }
        return ParamObjectImpl.makeList(paramss);
    }

    public List<ParamObject> getFromArchiveImage(final List<ArchivedImage> archiveImages) {
        int size = archiveImages.size();

        String[][] paramss = new String[size][2];
        for (int i = 0; i < size; i++) {
            paramss[i][0] = archiveImages.get(i).getId();
            paramss[i][1] = archiveImages.get(i).getName();
        }
        return ParamObjectImpl.makeList(paramss);
    }

    public List<ParamObject> getFromCategory(final List<Category> categories) {
        int size = categories.size();

        String[][] paramss = new String[size][2];
        for (int i = 0; i < size; i++) {
            paramss[i][0] = categories.get(i).getId();
            paramss[i][1] = categories.get(i).getPlanYear().toString();
        }
        return ParamObjectImpl.makeList(paramss);
    }

    @Override
    public List<ParamObject> getProgrammeClassificationList() {
        List<Parm> parms = parmDao.findBy(SEGMENT, PROGRAMME_CLASSICFICATION);
        return getFromParm(parms);
    }

    @Override
    public List<ParamObject> getDepartmentByCampus(final String campusCode) {
//        List<Dept> list = deptDao.findBy("campus", campusCode);
        List<Dept> list = deptDao.findByCampuse(campusCode);
        return getFromDept(list);
    }

    @Override
    public String getCampusLabel(final String campusCode) {
        Map<String, String> map = getCampusMap();
        return map.get(campusCode);
    }

    public Map<String, String> getCampusMap() {
        List<ParamObject> paramList = this.getCampusList();
        Map<String, String> map = new HashMap<String, String>();
        for (ParamObject param : paramList) {
            map.put(param.getCode(), param.getDesc());
        }
        return map;
    }

    @Override
    public String getDepartmentLabel(final String depCode, final String campusCode) {
        Map<String, String> map = getDepartmentMap(campusCode);
        return map.get(depCode);
    }

    public Map<String, String> getDepartmentMap(final String campusCode) {
        List<ParamObject> paramList = getDepartmentByCampus(campusCode);
        Map<String, String> map = new HashMap<String, String>();
        for (ParamObject param : paramList) {
            map.put(param.getCode(), param.getDesc());
        }
        return map;
    }

    public List<ParamObject> getFromDept(final List<Dept> depts) {
        int size = depts.size();

        String[][] paramss = new String[size][2];
        for (int i = 0; i < size; i++) {
//            log.info("getFromDept : {}", depts.get(i).getShortDesc());
            paramss[i][0] = depts.get(i).getDept();
            paramss[i][1] = depts.get(i).getShortDesc();
        }
        return ParamObjectImpl.makeList(paramss);
    }
}
